/**
* 补零
* @param {Number} val 数字
**/
const zeroize = function (val) {
	return val >= 10 ? val : '0' + val
}

/**
* 是否是链接
* @param {Number} url 链接
**/
const validateUrl = function (url) {
	return url.startsWith('http://') || url.startsWith('https://')
}

/**
* 是否是纯数字
* @param {Number} str 文本
**/
const validateNumber = function (str) {
	return /\d+/.test(str)
}

/**
* 是否是图片链接（包含base64判断）
* @param {Number} url 图片链接
**/
const validateImage = function (url) {
	const imageType = ['png', 'jpg', 'jpeg', 'gif', 'webp']
	return url.startsWith('data:image') || imageType.some(t => url.includes(t) || url.includes(t.toUpperCase()))
}

/**
* 复制文本
* @param {Number} text 字符串
**/
const copyText = function (text, message) {
	uni.setClipboardData({
		data: text,
		success: function () {
			uni.showToast({
				title: message || '复制成功',
				icon: 'none'
			})
		}
	});
}

/**
 * 文件大小格式化
 * @param {String} available 文件大小
 **/
const fileSizeFormat = function (available) {
	const size = available != 'null' ? available : 0;
	let fileSizeString;
	if(size == 0){
		fileSizeString = "0B";
	}else if(size < 1024){
		fileSizeString = size + "B";
	}else if(size < 1048576){
		fileSizeString = (size/1024).toFixed(2) + "KB";
	}else if (size < 1073741824){
		fileSizeString = (size/1048576).toFixed(2) + "MB";
	}else{
		fileSizeString = (size/1073741824).toFixed(2) + "GB";
	}
	return fileSizeString;
}

/**
 * 数字格式化
 * @param {Number} number 数字
 * @param {String} unit 单位
 * @param {Number} fixed 小数点最大保留多少位
 **/
const numberFormat = function (number, unit = '万', fixed = 2) {
	const units = {'亿': 100000000, '千万': 10000000, '百万': 1000000, '万': 10000, '千': 1000, '百': 100}
	const divisor = units[unit]
	if ( divisor ) {
		let num = (number / divisor).toString()
		if ( num.includes('.') && num.split('.')[1].length > fixed ) {
			num = (number / divisor).toFixed(2)
		}
		return num + unit
	}
	return num
}

/**
 * 时间格式化
 * @param {String} time 时间戳or时间
 **/
const dateFormat = function (time, formats = 'yyyy-mm-dd hh:mm:ss') {
	let arr = formats.split(' ')
	let dateFormats = ''
	let timeFormats = ''
	arr.forEach(item => {
		if ( item.indexOf('yy') > -1 ) {
			dateFormats = item
		} else {
			timeFormats = item
		}
	})
	const d = new Date(time);
	let result = ''
	if ( dateFormats.indexOf('yyyy') > -1 ) {
		result += d.getFullYear() + '-'
	}
	if ( dateFormats.indexOf('mm') > -1 ) {
		result += zeroize(d.getMonth() + 1) + '-'
	}
	if ( dateFormats.indexOf('dd') > -1 ) {
		result += zeroize(d.getDate()) + ' '
	}
	if ( timeFormats.indexOf('hh') > -1 ) {
		result += zeroize(d.getHours()) + ':'
	}
	if ( timeFormats.indexOf('mm') > -1 ) {
		result += zeroize(d.getMinutes()) + ':'
	}
	if ( timeFormats.indexOf('ss') > -1 ) {
		result += zeroize(d.getSeconds()) + ':'
	}
	return result.substring(0, result.length - 1)
}

/**
 * 秒数转化为时分秒
 * @param {String} value 秒数
 **/
const timeFormat = function (value, format = 'HH:mm:ss') {
	let hours ='00'
	if ( format.indexOf('HH') > -1 ) {
		hours = Math.floor(value / 60 / 60) >= 10 ? Math.floor(value / 60 / 60) : '0' + Math.floor(value / 60 / 60)
	}
	let minutes = '00'
	if ( format.split(':')[0] == 'HH' ) {
		minutes = Math.floor(value / 60 % 60) >= 10 ? Math.floor(value / 60 % 60) : '0' + Math.floor(value / 60 % 60)
	}
	if ( format.split(':')[0] == 'mm' ) {
		minutes = Math.floor(value / 60) >= 10 ? Math.floor(value / 60) : '0' + Math.floor(value / 60)
	}
	let seconds = Math.floor(value % 60) >= 10 ? Math.floor(value % 60) : '0' + Math.floor(value % 60);
	return format.indexOf('HH') > -1 ? hours + ':' + minutes + ':' + seconds : minutes + ':' + seconds
}
/**
 * 时间转化为秒数
 * @param {String} time 时间（HH:mm:ss）
 **/
const timeToSeconds = function (time){
	let arr = time.split(':')
	if ( arr.length == 2 ) arr.unshift('00')
	const seconds = parseInt(arr[0]) * 3600 + parseInt(arr[1]) * 60 + ( arr[2].indexOf('.') > -1 ? parseInt(arr[2].split('.')[0]) + parseInt(arr[2].split('.')[1]) / 1000 : parseInt(arr[2]) ) ;
	return seconds
}
/**
 * 移除url地址域名
 * @param {String} str http地址
 **/
const removeUrl = function (url) {
  	let str = url.replace(/^http:\/\/[^/]+/, '');
	return str.substr(1);
}
/**
 * 获取文件后缀
 * @param {String} name 带后缀的文件名称
 **/
const suffix = function (name) {
  	//获取图片后缀
  	let fileName = name.lastIndexOf(".");
  	let fileNameLength = name.length;
  	let fileFormat = name.substring(fileName + 1, fileNameLength);
  	return fileFormat.split('?')[0];
}
/**
 * 清除文件后缀
 * @param {String} name 带后缀的文件名称
*/
const removeSuffix = function (name) {
  	//获取图片后缀
  	let fileName = name.lastIndexOf(".");
	if ( fileName > -1 ) {
		let fileNameFormat = name.substring(0, fileName);
		return fileNameFormat;
	} else {
		return name
	}
}
/**
 * 链接参数拼接
 * @param {String} url 请求链接
 * @param {String} params 请求参数
*/
function urlPrams (url, params) {
	params = typeof params == 'object' ? params : [params]
	for (var k in params) {
	    let value = params[k] !== undefined ? params[k] : ''
		value = typeof value == 'string' ? value : JSON.stringify(value)
	    url +=(url.indexOf('?') < 0 ? '?' : '&') + `${k}=${encodeURIComponent(value)}`
	}
	return url
}
/**
 * 转化url参数为对象
 * @param {Array} href 携带参数的链接
*/
const convertUrlQueryObject = function(href) {
	const index = href.indexOf('?')
	const url = index > -1 ? href.substring(0, index) : href
	const search = index > -1 ? href.substring(index+1) : ''
	const vars = search.split('&')
	const obj = {}
    for (let i=0;i<vars.length;i++) {
        let pair = vars[i].split("=");
		obj[pair[0]] = pair[1]
    }
    return obj;
}
/**
 * 数组查找符合条件元素并返回下标
 * @param {Array} arr 传入数组
 * @param {String} value 条件元素
 * @param {String} query 对比key值
*/
const indexOf = function (arr, query, value) {
	let len = arr.length;
	for ( let i = 0; i < len; i++ ) {
		if ( arr[i][query] == value ) {
			return parseInt(i);
		}
	}
	return -1;
}
/**
 * 正则匹配
 * @param {String} type 匹配类型
 * @param {String} value 匹配值
*/
const validate = function (type, value) {
	const regs = {
		//身份证证则
		idcard: new RegExp(/^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/),
		//手机正则
		mobile: new RegExp(/^1[3456789]\d{9}$/),
		//固定电话正则
		phone: new RegExp(/^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}$/),
		//金额验证
		price: new RegExp(/^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0.\d{1,2}$/),
		//邮箱验证
		email: new RegExp(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/),
		//银行卡
		bankcard: new RegExp(/^([1-9]{1})(\d{15}|\d{18})$/)
	}
	return regs[type].test(value);
}
/**
 * 计算2个时间差的分钟数或者秒钟数或时钟数
 * @param {datetime} time1 开始时间
 * @param {datetime} time2 结束时间
*/
const timeMinuse = function (time1, time2, type = 'minutes') {
	//判断开始时间是否大于结束日期
	let date1 = new Date(time1);
	let date2 = new Date(time2);
	if	( date1 > date2 ) {
	  console.log("开始时间不能大于结束时间！");
	  return false;
	}
	let seconds = date2.getTime() / 1000 - date1.getTime() / 1000;
	return type == 'minutes' ? (seconds / 60) : type == 'hours' ? (seconds / 60 / 60) : seconds;
}
/**
 * 判断值类型返回字符
 * @param {datetime} value 需要判断类型的值
*/
const typeCall = function (value) {
	const type = Object.prototype.toString.call(value);
	return type.slice(8, type.length - 1)
}
/**
 * 生成随机字符串
 * @param {Number} len 长度
*/
const randomString = function (len) {
	len = len || 32;
	var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';    /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
	var maxPos = $chars.length;
	var pwd = '';
	for (let i = 0; i < len; i++) {
	　　pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
	}
	return pwd;
}
/**
 * 生成随机数字字符
 * @param {Number} len 长度
*/
const randomNumberString = function (len) {
	let min = 0;
	let max = len - 1;
	let arr = [];
	while ( arr.length < len ) {
		let value = Math.floor(Math.random() * (max - min + 1)) + min;
		if ( arr.indexOf(value) == -1 ) {
			arr.push( value )
		}
	}
	return arr.join('');
}
/**
 * 生成随机ID
*/
const randomId = function () {
	return new Date().getTime().toString() + Math.round(Math.random() * 10000);
}
/**
 * 生成随机不重复整数
 * @param {Number} len 长度
 * @param {Number} start 开始数字
*/
const randomSoleNumbers = function (len) {
	let min = 0;
	let max = len - 1;
	let arr = [];
	while ( arr.length < len ) {
		let value = Math.floor(Math.random() * (max - min + 1)) + min;
		if ( arr.indexOf(value) == -1 ) {
			arr.push( value )
		}
	}
	return arr;
}
/**
 * 16进制颜色转化为rgb
 * @param {String} hex 16进制颜色
*/
const hexToRgb = function (hex) {
	hex = hex.length == 7 ? hex : '#' + hex.slice(1, 4) + hex.slice(1, 4)
	let str="rgb("
	const r = parseInt(hex.slice(1,3),16).toString();   //ff  slice不包括end
	const g = parseInt(hex.slice(3,5),16).toString();   //00
	const b = parseInt(hex.slice(5,7),16).toString();   //ff
	str += r+","+g+","+b+")";
	return str
}
/**
 * rgb转化为16进制颜色
 * @param {String} rgb
*/
const rgbToHex = function (rgb) {
	rgb = rgb.replace('rgb(', '').replace(')', '')
	rgb = rgb.split(',')
	const r = parseInt(rgb[0], 10).toString(16);
	const g = parseInt(rgb[1], 10).toString(16);
	const b = parseInt(rgb[2], 10).toString(16);
	return '#' + (r.length == 2 ? r : r + r) + (g.length == 2 ? g : g + g) + (b.length == 2 ? b : b + b)
}
/**
 * 16进制颜色转化为rgba
 * @param {String} hex 16进制颜色
*/
const hexToRgba = function (hex, opacity) {
	hex = hex.length == 7 ? hex : '#' + hex.slice(1, 4) + hex.slice(1, 4)
	let str="rgba("
	const r = parseInt(hex.slice(1,3),16).toString();   //ff  slice不包括end
	const g = parseInt(hex.slice(3,5),16).toString();   //00
	const b = parseInt(hex.slice(5,7),16).toString();   //ff
	str += r+","+g+","+b+","+opacity+")";
	return str
}
/**
 * rgba转化为16进制颜色
 * @param {String} rgba
*/
const rgbaToHex = function (rgba) {
	rgba = rgba.replace('rgba(', '').replace(')', '')
	rgba = rgba.split(',')
	const r = parseInt(rgba[0], 10).toString(16);
	const g = parseInt(rgba[1], 10).toString(16);
	const b = parseInt(rgba[2], 10).toString(16);
	return '#' + (r.length == 2 ? r : r + r) + (g.length == 2 ? g : g + g) + (b.length == 2 ? b : b + b)
}
/**
 * 10进制颜色转化为rgb
 * @param {String} decimal 10进制颜色
*/
const decimalToRgb = function (decimal) {
	const r = (decimal >> 16) & 255;
	const g = (decimal >> 8) & 255;
	const b = decimal & 255;
	return 'rgb(' + r + ',' + g + ',' + b + ')'
}
/**
 * unicode转换为中文或字符串
 * @param {String} str
*/
const uncode = function (str) {
	return str.replace(/&#(x)?([^&]{1,5});?/g, function (a, b, c) {
		return String.fromCharCode(parseInt(c, b ? 16 : 10));
	})
}
// 深度克隆
const deepClone = function (obj) {  
    if (obj === null || typeof obj !== 'object') {
        return obj;
    }
    
    if (obj instanceof Date) {
        return new Date(obj.getTime());
    }
    
    if (Array.isArray(obj)) {
        return obj.map(item => deepClone(item));
    }
    
    if (typeof obj === 'object') {
        const clonedObj = {};
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                clonedObj[key] = deepClone(obj[key]);
            }
        }
        return clonedObj;
    }
    
    return obj;
}
/**
 * 删除对象指定属性
 * @param {Object} object 目标对象
 * @param {String} key 目标属性（多个以,分隔）
*/
const deleteProperty = function (object, key) {
	const obj = {}
	const keys = key.split(',').map(s => s.trim())
	Object.keys(object).forEach(k => {
		if ( !keys.includes(k) ) obj[k] = object[k]
	})
	return obj
}
/**
 * 删除对象中的空值属性
 * @param {Object} object 目标对象
*/
const removeEmptyProperty = function (object) {//移除空值属性
    if (typeof object !== 'object' || object === null) {
        return object;
    }
    if (Array.isArray(object)) {
        return object.map(item => removeEmptyProperty(item)).filter(item => item !== null && item !== undefined && item !== "" && !(Array.isArray(item) && item.length === 0) && !(typeof item === 'object' && Object.keys(item).length === 0));
    }
    const newObj = {};
    for (const key in object) {
        if (object.hasOwnProperty(key)) {
            const value = removeEmptyProperty(object[key]);
            if (value !== null && value !== undefined && value !== "" && !(Array.isArray(value) && value.length === 0) && !(typeof value === 'object' && Object.keys(value).length === 0)) {
                newObj[key] = value;
            }
        }
    }
    return newObj;
}
/**
 * 判断数组是否包含另一个数组
 * @param {a} Array 包含数组
 * @param {b} Array 被包含数组
*/
const isContained = function (a, b){
    if( typeCall(a) != 'Array' || typeCall(b) != 'Array' ) return false;
    if(a.length < b.length) return false;
	for ( let i = 0; i < b.length; i++ ) {
		for(let j = 0; j < a.length; j++){
		    if(JSON.stringify(b[i]) == JSON.stringify(a[j])) break;
			if ( j == a.length - 1 ) return false
		}
	}
    return true;
}
/**
 * 判断像素单位，没有则加上rpx
 * @param {String} value 像素
*/
const pixelunit = function (value) {
	if ( value.toString().indexOf('px') > -1 || value.toString().indexOf('em') > -1 || value.toString().indexOf('auto') > -1 || value.toString().indexOf('%') > -1 ) {
		return value
	} else {
		return value + 'rpx'
	}
}
/**
 * 判断像素单位，全部转为px
 * @param {String} value 像素
*/
const unitpixel = function (value) {
	if ( value.toString().indexOf('rpx') > -1 ) {
		return uni.upx2px(value.replace('rpx', ''))
	} else if ( value.toString().indexOf('px') > -1 ) {
		return parseFloat(value.replace('px', ''))
	} else if ( value.toString().indexOf('em') > -1 || value.toString().indexOf('auto') > -1 || value.toString().indexOf('%') > -1 ) {
		return value
	} else {
		return parseFloat(uni.upx2px(value))
	}
}
/**
 * 判断像素单位，转化为rpx
 * @param {String} value 值
 * @param {String} unit 返回结果是否带上单位
*/
const anytorpx = function (value, unit = true) {
	if ( value.toString().indexOf('rpx') > -1 ) {
		return unit ? value : parseFloat(value.replace('rpx', ''))
	} else if ( value.toString().indexOf('px') > -1 ) {
		return parseFloat(value.replace('px', '') * (750 / uni.getSystemInfoSync().windowWidth)) + (unit ? 'rpx' : 0)
	} else if ( value.toString().indexOf('auto') > -1 ) {
		return 'auto'
	} else if ( value.toString().indexOf('%') > -1 ) {
		return parseFloat((value.replace('%', '') / 100) * 750) + (unit ? 'rpx' : 0)
	} else if (value.toString().indexOf('em') > -1 || value.toString().indexOf('rem') > -1 ) {
		return parseFloat(value.replace('em', '').replace('rem', '') * 32) + (unit ? 'rpx' : 0)
	} else if ( /^\d+$/.test(value) ) {
		return parseFloat(value) + (unit ? 'rpx' : 0)
	}
}
/**
 * 判断像素单位，转化为px
 * @param {String} value 值
 * @param {String} unit 返回结果是否带上单位
*/
const anytopx = function (value, unit = false) {
	if ( value.toString().indexOf('rpx') > -1 ) {
		return uni.upx2px(value.replace('rpx', '')) + (unit ? 'px' : 0)
	} else if ( value.toString().indexOf('px') > -1 ) {
		return parseFloat(value.replace('px', '')) + (unit ? 'px' : 0)
	} else if ( value.toString().indexOf('auto') > -1 ) {
		return 'auto'
	} else if ( value.toString().indexOf('%') > -1 ) {
		return parseFloat((value.replace('%', '') / 100) * uni.getSystemInfoSync().windowWidth) + (unit ? 'px' : 0)
	} else if (value.toString().indexOf('em') > -1 || value.toString().indexOf('rem') > -1 ) {
		return parseFloat(value.replace('em', '').replace('rem', '') * uni.getSystemInfoSync().windowWidth) + (unit ? 'px' : 0)
	} else if ( /^\d+$/.test(value) ) {
		return parseFloat(value) + (unit ? 'px' : 0)
	}
}
const getRefs = function (components, name, current) {
	// #ifndef MP
	return current >= 0 ? components.$refs[name][current] : components.$refs[name]
	// #endif
	// #ifdef MP
	return {}
	// #endif
}
//获取节点
const getEl = function (el) {
    if (typeof el === 'string' || typeof el === 'number') return el;
	if (WXEnvironment) {
	    return el.ref;
	} else {
	    return el instanceof HTMLElement ? el : el.$el;
	}
}
/**
 * 获取指定父节点
 * @param {String} components 当前实例
 * @param {String} name 父节点名称
*/
const getParent = function(name, components) {
	let parent = components.$parent
	if (parent) {
		let parentName = parent.$options.name
		while (parentName !== name) {
			parent = parent.$parent
			if (parent) {
				parentName = parent.$options.name
			} else {
				return null
			}
		}
		return parent
	}
	return null
}
/**
 * 获取指定子节点
 * @param {String} components 当前实例
 * @param {String} name 父节点名称
*/
const getChildrens = function (names, components) {
	let arr = []
	let childs = names.split(',')
	const dowhile = (children) => {
		if ( typeCall(children) == 'Array' ) {
			children.forEach(child => {
				if ( childs.indexOf(child.$options.name) > -1 ) {
					arr.push(child)
				}
				if ( child.$children && child.$children.length > 0 ) {
					dowhile(child.$children)
				}
			})
		}
	}
	dowhile(components.$children)
	return arr;
}
/**
 * 获取尺寸信息
 * @param {String} selector 节点class或者id
 * @param {String} el 节点
 * @param {String} components 当前实例
*/
const getRect = function (selector, el, components) {
	return new Promise(resolve => {
		// #ifdef APP-NVUE
		uni.requireNativePlugin('dom').getComponentRect(el, res => {
			resolve(res.size)
		})
		// #endif
		// #ifndef APP-NVUE
		uni.createSelectorQuery().in(components).select(selector).boundingClientRect(data => {
			resolve(data)
		}).exec();
		// #endif
	})
}


module.exports = {
	zeroize,
	validateNumber,
	validateUrl,
	validateImage,
	copyText,
	numberFormat,
	dateFormat,
	timeFormat,
	fileSizeFormat,
	timeToSeconds,
	removeUrl,
	suffix,
	removeSuffix,
	urlPrams,
	convertUrlQueryObject,
	indexOf,
	validate,
	timeMinuse,
	typeCall,
	randomString,
	randomNumberString,
	randomId,
	randomSoleNumbers,
	hexToRgb,
	rgbToHex,
	decimalToRgb,
	hexToRgba,
	rgbaToHex,
	uncode,
	deepClone,
	deleteProperty,
	removeEmptyProperty,
	isContained,
	pixelunit,
	unitpixel,
	anytorpx,
	anytopx,
	getRefs,
	getEl,
	getParent,
	getChildrens,
	getRect
}